#include "rfid_api.h"
#include "iso14443a.h"
#include "mifare_api.h"
#include "rfid_board.h"

#if _RFID_FUNCTION_ENABLE_

bool MifareAuthentication(uint8_t AuthMode, uint8_t BlockAddr, uint8_t *pKey, uint8_t *pSnr)
{
  uint16_t AuthStateDataSize = 0;
  uint8_t AuthStateResult = MI_ERR, AuthStateDataBuff[MAXRLEN] = {0};

  if ((pKey != NULL) && (pSnr != NULL))
  {
    AuthStateDataBuff[AuthStateDataSize++] = AuthMode;
    AuthStateDataBuff[AuthStateDataSize++] = BlockAddr;
    memcpy(&AuthStateDataBuff[AuthStateDataSize], pKey, CARD_VERIFY_KEY_LENGTH);
    AuthStateDataSize += CARD_VERIFY_KEY_LENGTH;
    memcpy(&AuthStateDataBuff[AuthStateDataSize], pSnr, RFID_NUMBER_OF_MIFARE_CARD_SERIAL_NUMBER);
    AuthStateDataSize += 4;

    RfidPcdSetTimer(5);
    AuthStateResult = RfidPcdCommunication(PCD_AUTHENT, AuthStateDataBuff, (uint8_t)AuthStateDataSize, AuthStateDataBuff, &AuthStateDataSize);
    if (RfidPcdReadReg(JREG_STATUS2) & 0x08)
      return true;
  }

  return false;
}

bool MifareBlockWrite(uint8_t BlockAddr, const uint8_t *pDataIn, uint8_t DataSize)
{
  uint16_t BlockWriteDataSize = 0;
  uint8_t BlockWriteResult = MI_ERR, BlockWriteDataBuff[MAXRLEN] = {0};

  if (pDataIn != NULL)
  {
    if ((DataSize != 0) && (DataSize <= MIFARE_CARD_BLOCK_DATA_LENGTH))
    {
      BlockWriteDataBuff[BlockWriteDataSize++] = PICC_WRITE;
      BlockWriteDataBuff[BlockWriteDataSize++] = BlockAddr;

      RfidPcdSetTimer(5);
      BlockWriteResult = RfidPcdCommunication(PCD_TRANSCEIVE, BlockWriteDataBuff, (uint8_t)BlockWriteDataSize, BlockWriteDataBuff, &BlockWriteDataSize);
      if ((BlockWriteDataSize == 4) && ((BlockWriteDataBuff[0] & 0x0F) == 0x0A))
      {
        BlockWriteDataSize = DataSize;
        memcpy(BlockWriteDataBuff, pDataIn, DataSize);

        RfidPcdSetTimer(10);
        BlockWriteResult = RfidPcdCommunication(PCD_TRANSCEIVE, BlockWriteDataBuff, (uint8_t)BlockWriteDataSize, BlockWriteDataBuff, &BlockWriteDataSize);
        if ((BlockWriteDataSize == 4) && ((BlockWriteDataBuff[0] & 0x0F) == 0x0A))
          return true;
      }
    }
  }

  return false;
}

bool MifareBlockRead(uint8_t BlockAddr, uint8_t *pDataOut)
{
  uint16_t ReadDataSize = 0;
  uint8_t ReadResult = MI_ERR, ReadDataBuff[MAXRLEN] = {0};

  if (pDataOut != NULL)
  {
    ReadDataBuff[ReadDataSize++] = PICC_READ;
    ReadDataBuff[ReadDataSize++] = BlockAddr;

    RfidPcdSetTimer(5);
    ReadResult = RfidPcdCommunication(PCD_TRANSCEIVE, ReadDataBuff, (uint8_t)ReadDataSize, ReadDataBuff, &ReadDataSize);
    if ((ReadResult == MI_OK) && (ReadDataSize == MIFARE_CARD_BLOCK_DATA_LENGTH * 8))
    {
      memcpy(pDataOut, ReadDataBuff, MIFARE_CARD_BLOCK_DATA_LENGTH);
      return true;
    }
  }

  return false;
}

bool MifareChangeKey(uint8_t SectorId, const uint8_t *pNewKeyInA, const uint8_t *pNewKeyInB)
{
  bool ChangeKeyResult = false;
  uint16_t ChangeKeyDataSize = 0;
  uint8_t ChangeKeyDataBuff[MAXRLEN] = {0};

  if ((SectorId >= MIFARE_START_SECTOR_ID) && (SectorId <= MIFARE_END_SECTORD_ID))
  {
    if ((pNewKeyInA != NULL) && (pNewKeyInB != NULL))
    {
      memcpy(&ChangeKeyDataBuff[ChangeKeyDataSize], pNewKeyInA, CARD_VERIFY_KEY_LENGTH);
      ChangeKeyDataSize += CARD_VERIFY_KEY_LENGTH;
      ChangeKeyDataBuff[ChangeKeyDataSize++] = 0xFF;
      ChangeKeyDataBuff[ChangeKeyDataSize++] = 0x07;
      ChangeKeyDataBuff[ChangeKeyDataSize++] = 0x80;
      ChangeKeyDataBuff[ChangeKeyDataSize++] = 0x69;
      memcpy(&ChangeKeyDataBuff[ChangeKeyDataSize], pNewKeyInB, CARD_VERIFY_KEY_LENGTH);
      ChangeKeyDataSize += CARD_VERIFY_KEY_LENGTH;

      ChangeKeyResult = MifareBlockWrite((SectorId * 4) + 3, ChangeKeyDataBuff, ChangeKeyDataSize);
      if (ChangeKeyResult == true)
        return true;
    }
  }

  return false;
}

bool MifareInitializeSector(uint8_t SectorId)
{
  uint8_t InitDataBuff[MIFARE_CARD_BLOCK_DATA_LENGTH] = {0};

  if ((SectorId >= MIFARE_START_SECTOR_ID) && (SectorId <= MIFARE_END_SECTORD_ID))
  {
    for (uint8_t i = 0; i < 3; i++)
    {
      if (MifareBlockWrite(((SectorId * 4) + i), InitDataBuff, MIFARE_CARD_BLOCK_DATA_LENGTH) == false)
        return false;
    }

    memset(InitDataBuff, 0xFF, CARD_VERIFY_KEY_LENGTH);
    if (MifareChangeKey(SectorId, InitDataBuff, InitDataBuff) == true)
      return true;
  }

  return false;
}

#endif
